package crl.encrypt.inject
{
	import com.swfwire.decompiler.abc.ABCFile;
	import com.swfwire.decompiler.abc.instructions.IInstruction;
	import com.swfwire.decompiler.abc.instructions.Instruction_astype;
	import com.swfwire.decompiler.abc.instructions.Instruction_debugfile;
	import com.swfwire.decompiler.abc.instructions.Instruction_jump;
	import com.swfwire.decompiler.abc.instructions.Instruction_label;
	import com.swfwire.decompiler.abc.instructions.Instruction_newobject;
	import com.swfwire.decompiler.abc.instructions.Instruction_setlocal0;
	import com.swfwire.decompiler.abc.tokens.InstanceToken;
	import com.swfwire.decompiler.abc.tokens.MethodBodyInfoToken;
	import com.swfwire.decompiler.abc.tokens.MethodInfoToken;
	import com.swfwire.decompiler.abc.tokens.MultinameToken;
	import com.swfwire.decompiler.abc.tokens.StringToken;
	import com.swfwire.decompiler.abc.tokens.multinames.MultinameQNameToken;
	
	import crl.encrypt.ext.PlayerGlobalDefine;
	
	import flash.utils.Dictionary;

	/**
	 * 
	 * @author crl
	 * 
	 */	
	public class Inject implements IInject
	{
		private var excludeNamespace:Dictionary;
		private var methodAndBodyRef:Dictionary;
		public function Inject()
		{
			excludeNamespace=PlayerGlobalDefine.instance.namespa;
			methodAndBodyRef=new Dictionary();
		}
		
		public function reset():void{
			
		}
		
		public function end():void{
			methodAndBodyRef=new Dictionary();
		}
		
		public function injectABC(abc:ABCFile):void{
			//return;
			var method:MethodInfoToken;
			var methods:Vector.<MethodInfoToken>=abc.methods;
			var methodBody:MethodBodyInfoToken;
			
			for each(methodBody in abc.methodBodies){
				method=methods[methodBody.method];	
				methodAndBodyRef[method]=methodBody;
			}

			var strings:Vector.<StringToken>=abc.cpool.strings;
			var multinames:Vector.<MultinameToken>=abc.cpool.multinames;
			var multiname:MultinameToken;
			var name:String;
			for each(var instance:InstanceToken in abc.instances){
				if(instance.flags&0x04){
					continue;
				}
				multiname=multinames[instance.name];
				
				if(multiname.kind==7){
					name=strings[(multiname.data as MultinameQNameToken).name].utf8;
				}else{
					continue;
				}
				
				//trace(name,multiname.kind);
				
				if(name in excludeNamespace){
					continue;
				}
				methodBody=methodAndBodyRef[abc.methods[instance.iinit]];
				if(methodBody)inject(methodBody.instructions,methodBody);
			}
		}
		
		/**
		 * 注入代码 
		 * @param opcodes
		 * @param methodBody
		 * 
		 */		
		public function inject(opcodes:Vector.<IInstruction>,methodBody:MethodBodyInfoToken):void{

				//注入一个跳转代码,在中间插入创建无数个对像;(可使硕思崩溃);
				var jump:Instruction_jump=new Instruction_jump();
				jump.offset=5;//框架内部会自己处理;
				
				insert[0]=jump;
				insert[1]=new Instruction_newobject(10000000);
				insert[2]=new Instruction_setlocal0();
				insert[3]=new Instruction_label();
				
				jump.reference=insert[3];
				
				var star:int=2;
				if(opcodes[0] is Instruction_debugfile){
					star=4;
				}
				
				opcodes.splice(2,0,insert[0],insert[1],insert[2],insert[3]);
		}
		
		private var insert:Array=[];
	}
}